using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using SadlandVillage.Core;
using SadlandVillage.Core.Helper;

namespace SadlandVillage
{
  /// <summary>
  /// This is the main type for your game
  /// </summary>
  public class Map : GameScene
  {

    #region PrivateTypes
    /// <summary>
    /// Some tiles based on included media
    /// </summary>
    public enum TileName : int
    {
      Empty = 0,
      Base = 1,
      Transiction = 2,
      Objects = 3,
      Clouds = 4
    }

    /// <summary>
    /// Map height and width of the map
    /// </summary>

    #endregion

    #region Constants
    private const float MovementRate = 500f;
    private const float ZoomRate = 1f;
    private const float RotationRate = 1.5f;
    private const int numTiles = 1; //200
    private const float animationTime = 0.1f;
    private static readonly Vector2 animatedSpriteScale = new Vector2(1f, 1f);


    private const int enterGameSeconds = 4;
    private const int MAP_WIDTH = 2048;
    private const int MAP_HEIGHT = 1638;
    private const int CURSOR_WIDTH = 120;
    private const int CURSOR_HEIGHT = 120;




    #endregion

    #region Fields
    //utility types
    GraphicsDeviceManager graphics;

    //input state storage
    KeyboardState lastKeyboardState = new KeyboardState();
    GamePadState lastGamePadState = new GamePadState();
    KeyboardState currentKeyboardState = new KeyboardState();
    GamePadState currentGamePadState = new GamePadState();

    private Dictionary<GameBuilding, string> gameBuildings;

    //2D camera abstraction
    private Camera2D camera;
    private Vector2 screenCenter;

    //tile information
    private SpriteSheet groundSheet;
    private SpriteSheet cloudSheet;
    //private SpriteBatch spriteBatch;
    private TileGrid groundLayer;
    private TileGrid cloudLayer;

    //animated sprite
    private SpriteSheet animatedSpriteSheet;
    private AnimatedSprite animatedSprite;
    private Vector2 animatedSpritePosition;
    private float accumulator;

    private static int lastMouseX;
    private static int lastMouseY;

    private static int lastWiimoteX;
    private static int lastWiimoteY;
    #endregion


    //Statics sprites
    private SpriteSheet gameBoxSheet;
    private MessageSprite gameBoxSprite;

    // What direction are we moving (0=up, 1=down, 2=left, 3=right)
    int iMoveDirection = 0;
    int m_Move = 0;
    int lastX = 0;
    int lastY = 0;



    #region Initialization

    public Map(ContentManager content, SpriteBatch spriteBatch)
      : base(content, spriteBatch)
    {
      //graphics = new GraphicsDeviceManager(this);
      //Content.RootDirectory = "Content";

      //graphics.PreferredBackBufferWidth = 800;
      //graphics.PreferredBackBufferHeight = 600;
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    public override void LoadContent()
    {

      gameBuildings = new Dictionary<GameBuilding, string>();
      gameBuildings.Add(GameBuilding.Home, "Player's House");
      gameBuildings.Add(GameBuilding.Restaurant, "Clotilde's Restaurant");
      gameBuildings.Add(GameBuilding.River, "River House");
      gameBuildings.Add(GameBuilding.Pub, "Pub House");
      gameBuildings.Add(GameBuilding.Forest, "Forest House");
      gameBuildings.Add(GameBuilding.GamerHouse, "Gamer House");
      gameBuildings.Add(GameBuilding.HorrorHouse, "Haunted House");

      #region Set up Graphics resources
      Texture2D groundTexture = content.Load<Texture2D>(@"Map\Textures\mapa03_objects_flat_2048");
      Texture2D cloudTexture = content.Load<Texture2D>(@"Map\Textures\clouds");
      Texture2D gameBoxTexture = content.Load<Texture2D>(@"Map\Sprites\gameBox");

      //spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
      #endregion

      #region Set Up Tile Sources
      //set up the tile sheets with source rectangles
      //for each of the different sprites
      cloudSheet = new SpriteSheet(cloudTexture);
      cloudSheet.AddSourceSprite((int)TileName.Clouds,
          new Rectangle(0, 0, 1024, 1024));

      groundSheet = new SpriteSheet(groundTexture);
      groundSheet.AddSourceSprite((int)TileName.Base,
          new Rectangle(0, 0, MAP_WIDTH, MAP_HEIGHT));

      #endregion

      #region Setup Tile Grids
      //Create the ground layer tile
      groundLayer = new TileGrid(MAP_WIDTH, MAP_HEIGHT, numTiles, numTiles,
          Vector2.Zero, groundSheet, graphics);

      int numCloudTiles = numTiles / 6 + 1;
      cloudLayer = new TileGrid(1024, 1024, numCloudTiles, numCloudTiles,
          Vector2.Zero, cloudSheet, graphics);

      //These loops fill the datas with some appropriate data.  
      //The clouds and ground clutter have been randomized.
      for (int i = 0; i < numTiles; i++)
      {
        for (int j = 0; j < numTiles; j++)
        {
          groundLayer.SetTile(i, j, 1);
        }
      }

      for (int i = 0; i < numCloudTiles; i++)
      {
        for (int j = 0; j < numCloudTiles; j++)
        {

          cloudLayer.SetTile(i, j, (int)TileName.Clouds);

        }
      }
      #endregion

      // Set up AnimatedSprite
      animatedSpriteSheet = new SpriteSheet(content.Load<Texture2D>(@"Map\Sprites\cursor2"));

      animatedSprite = new AnimatedSprite(animatedSpriteSheet, 60, 60, 0,
          1, 4, new Point(0, 0), 4);

      gameBoxSheet = new SpriteSheet(content.Load<Texture2D>(@"Map\Sprites\gameBox"));
      gameBoxSprite = new MessageSprite(gameBoxSheet, 240, 100);
      gameBoxSprite.FontTexture = content.Load<SpriteFont>(@"Map\Sprites\myFont");

      // Set Up a 2D Camera
      camera = new Camera2D();

      ResetToInitialPositions();
    }


    /// <summary>
    /// Reset the camera to the center of the tile grid
    /// and reset the position of the animted sprite
    /// </summary>
    private void ResetToInitialPositions()
    {
      //set up the 2D camera
      //set the initial position to the center of the
      //tile field
      camera.Position = Vector2.Zero;
      camera.Rotation = 0f;
      camera.Zoom = 1f;
      camera.MoveUsingScreenAxis = true;

      //the animated sprite has no concept of a camera, so 
      //making the sprite camera relative is the job
      //of the game program

      animatedSpritePosition = camera.Position;
      animatedSprite.ScaleValue = animatedSpriteScale;
      animatedSprite.Position = screenCenter;

      gameBoxSprite.Position = camera.Position;
      gameBoxSprite.ScaleValue = animatedSpriteScale;

      CameraChanged();
    }
    #endregion


    #region Update and Render

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    public override void Update(GameTime gameTime)
    {
      // Allows the game to exit
      //if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
      //  this.Exit();

      HandleInput();

      //Set the camera's state to Unchanged for this frame
      //this will save us from having to update visibility if the camera
      //does not move
      camera.ResetChanged();

      //Call sample-specific input handling function
      HandleKeyboardInput((float)gameTime.ElapsedGameTime.TotalSeconds);
      HandleGamePadInput((float)gameTime.ElapsedGameTime.TotalSeconds);

      HandleCursorInput((float)gameTime.ElapsedGameTime.TotalSeconds);
      HandleWiimoteInput((float)gameTime.ElapsedGameTime.TotalSeconds);

      if (camera.IsChanged)
      {
        CameraChanged();
      }


      //thottle the animation update speed to the frame animation
      //time
      accumulator += (float)gameTime.ElapsedGameTime.TotalSeconds;
      if (accumulator > animationTime)
      {
        animatedSprite.IncrementAnimationFrame();
        accumulator -= animationTime;
      }


      //Test code
      if (Input.KeyPressed(Keys.C))
      {
        StartMiniGame(MiniGameType.Club);
      }

      if (Input.KeyPressed(Keys.R))
      {
        StartMiniGame(MiniGameType.Restaurant);
      }

      if (Input.KeyPressed(Keys.M))
      {
        StartMiniGame(MiniGameType.Microgames);
      }

      if (Input.KeyPressed(Keys.Escape))
      {
        PauseGame();
      }

      if (Input.KeyPressed(Keys.B))
      {
        StartMiniGame(MiniGameType.River);
      }

      if (Input.KeyPressed(Keys.H))
      {
          StartMiniGame(MiniGameType.Mansion);
      }

      //base.Update(gameTime);
    }

    private void HandleWiimoteInput(float elapsed)
    {

    }

    #region Input Handling Functions

    /// <summary>
    /// Handle Game Pad input during Update
    /// </summary>
    public void HandleGamePadInput(float elapsed)
    {
      if (currentGamePadState.IsConnected)
      {
        //the left thumbstick moves the animated sprite around the world
        if ((Math.Abs(currentGamePadState.ThumbSticks.Left.X) > .1f) ||
            (Math.Abs(currentGamePadState.ThumbSticks.Left.Y) > .1f))
        {
          //Sprite movement is being updated relative to the camera
          //rotation
          animatedSpritePosition.X += (float)Math.Cos(-camera.Rotation) *
              currentGamePadState.ThumbSticks.Left.X * elapsed * MovementRate;
          animatedSpritePosition.Y += (float)Math.Sin(-camera.Rotation) *
              currentGamePadState.ThumbSticks.Left.X * elapsed * MovementRate;
          animatedSpritePosition.Y -= (float)Math.Cos(camera.Rotation) *
              currentGamePadState.ThumbSticks.Left.Y * elapsed * MovementRate;
          animatedSpritePosition.X -= (float)Math.Sin(camera.Rotation) *
              currentGamePadState.ThumbSticks.Left.Y * elapsed * MovementRate;

          //since the sprite position has changed, the Origin must be updated
          //on the animated sprite object
          animatedSprite.Origin = (camera.Position - animatedSpritePosition)
              / animatedSpriteScale.X;
        }
        //right thumbstick controls the camera position
        if ((Math.Abs(currentGamePadState.ThumbSticks.Right.X) > .1f) ||
            (Math.Abs(currentGamePadState.ThumbSticks.Right.Y) > .1f))
        {
          float dX = currentGamePadState.ThumbSticks.Right.X * elapsed *
              MovementRate;
          float dY = currentGamePadState.ThumbSticks.Right.Y * elapsed *
              MovementRate;
          camera.MoveRight(ref dX);
          camera.MoveUp(ref dY);
        }
        //the triggers control rotation
        if ((Math.Abs(currentGamePadState.Triggers.Left) > .1f) ||
            (Math.Abs(currentGamePadState.Triggers.Right) > .1f))
        {
          float dX = currentGamePadState.Triggers.Left *
              elapsed * RotationRate;
          dX += -currentGamePadState.Triggers.Right *
              elapsed * RotationRate;
          camera.Rotation += dX;
        }
        //the A and B buttons control zoom
        if ((currentGamePadState.Buttons.A == ButtonState.Pressed) ||
            (currentGamePadState.Buttons.B == ButtonState.Pressed))
        {
          float delta = elapsed * ZoomRate;
          if (currentGamePadState.Buttons.B == ButtonState.Pressed)
            delta = -delta;

          camera.Zoom += delta;
          if (camera.Zoom < .5f) camera.Zoom = .5f;
          if (camera.Zoom > 2f) camera.Zoom = 2f;
        }
        if ((currentGamePadState.Buttons.RightStick == ButtonState.Pressed) &&
            (lastGamePadState.Buttons.RightStick == ButtonState.Released))
        {
          ResetToInitialPositions();
        }
      }
    }

    /// <summary>
    /// Handle Keyboard input during Update
    /// </summary>
    public void HandleKeyboardInput(float elapsed)
    {
      //check for camera movement
      float dX = ReadKeyboardAxis(currentKeyboardState, Keys.Left, Keys.Right) *
          elapsed * MovementRate;
      float dY = ReadKeyboardAxis(currentKeyboardState, Keys.Down, Keys.Up) *
          elapsed * MovementRate;

      //check for animted sprite movement
      animatedSpritePosition.X += (float)Math.Cos(-camera.Rotation) *
          ReadKeyboardAxis(currentKeyboardState, Keys.Left, Keys.Right) *
          elapsed * MovementRate;

      animatedSpritePosition.Y += (float)Math.Sin(-camera.Rotation) *
          ReadKeyboardAxis(currentKeyboardState, Keys.Left, Keys.Right) *
          elapsed * MovementRate;

      animatedSpritePosition.X -= (float)Math.Sin(camera.Rotation) *
          ReadKeyboardAxis(currentKeyboardState, Keys.Down, Keys.Up) *
          elapsed * MovementRate;
      animatedSpritePosition.Y -= (float)Math.Cos(camera.Rotation) *
          ReadKeyboardAxis(currentKeyboardState, Keys.Down, Keys.Up) *
          elapsed * MovementRate;

      if (animatedSpritePosition.X < 0) animatedSpritePosition.X = 0;
      if (animatedSpritePosition.Y < 0) animatedSpritePosition.Y = 0;

      if (animatedSpritePosition.X > (MAP_WIDTH - CURSOR_WIDTH)) animatedSpritePosition.X = (MAP_WIDTH - CURSOR_WIDTH);
      if (animatedSpritePosition.Y > (MAP_HEIGHT - CURSOR_HEIGHT)) animatedSpritePosition.Y = (MAP_HEIGHT - CURSOR_HEIGHT);

      dX = ReadKeyboardAxis(currentKeyboardState, Keys.Left, Keys.Right) *
          elapsed * MovementRate;
      dY = ReadKeyboardAxis(currentKeyboardState, Keys.Down, Keys.Up) *
          elapsed * MovementRate;

      if (currentKeyboardState.IsKeyDown(Keys.Down))
      {
        if (animatedSpritePosition.Y - camera.Position.Y > 380 / camera.Zoom)
        {
          camera.MoveUp(ref dY);
        }
      }
      if (currentKeyboardState.IsKeyDown(Keys.Up))
      {
        if (animatedSpritePosition.Y - camera.Position.Y < 50 / camera.Zoom)
        {
          camera.MoveUp(ref dY);
        }
      }

      if (currentKeyboardState.IsKeyDown(Keys.Right))
      {
        if (animatedSpritePosition.X - camera.Position.X > 580 / camera.Zoom)
        {
          camera.MoveRight(ref dX);
        }
      }
      if (currentKeyboardState.IsKeyDown(Keys.Left))
      {
        if (animatedSpritePosition.X - camera.Position.X < 50 / camera.Zoom)
        {
          camera.MoveRight(ref dX);
        }
      }


      //Verifying if will show gameBox
      Vector2 origin = Vector2.Zero;
      foreach (GameBuilding gb in gameBuildings.Keys)
      {
        if (animatedSpritePosition.X > GetBuildingRectangle(gb).Left
          && animatedSpritePosition.X < GetBuildingRectangle(gb).Left + GetBuildingRectangle(gb).Width
          && animatedSpritePosition.Y > GetBuildingRectangle(gb).Top
          && animatedSpritePosition.Y < GetBuildingRectangle(gb).Top + GetBuildingRectangle(gb).Height)
        {
          //Verifying if he enter in the rectangle to get enter in the game
          Vector2 pos = -camera.Position + gameBoxSprite.Origin + animatedSpritePosition;
          if (pos.X > 167 && pos.X < 240 - 60 - 3
            && pos.Y > 26 && pos.Y < 100 - 60 - 3)
          {
            //Do Nothing
          }
          else
          {
            if (-camera.Position.X + GetBuildingRectangle(gb).Left + (GetBuildingRectangle(gb).Width / 2) + 240 < 800)
            {
              origin = new Vector2(-camera.Position.X + GetBuildingRectangle(gb).Left + (GetBuildingRectangle(gb).Width / 2), -camera.Position.Y + GetBuildingRectangle(gb).Top + (GetBuildingRectangle(gb).Height / 2));
              //gameBoxSprite.Position = new Vector2(-camera.Position.X + GetBuildingRectangle(gb).Left + (GetBuildingRectangle(gb).Width / 2), -camera.Position.Y + GetBuildingRectangle(gb).Top + (GetBuildingRectangle(gb).Height / 2));
            }
            else
            {
              origin = new Vector2(-camera.Position.X + GetBuildingRectangle(gb).Left - (GetBuildingRectangle(gb).Width / 2), -camera.Position.Y + GetBuildingRectangle(gb).Top + (GetBuildingRectangle(gb).Height / 2));
              //gameBoxSprite.Position = new Vector2(-camera.Position.X + GetBuildingRectangle(gb).Left - (GetBuildingRectangle(gb).Width / 2), -camera.Position.Y + GetBuildingRectangle(gb).Top + (GetBuildingRectangle(gb).Height / 2));
            }

            gameBoxSprite.Building = gb;
            gameBoxSprite.Visible = true;
            gameBoxSprite.Origin = -origin;
            gameBoxSprite.Text = gameBuildings[gb];
          }
        }
      }


      //since the sprite position has changed, the Origin must be updated
      //on the animated sprite object

      animatedSprite.Origin = (camera.Position - animatedSpritePosition)
              / animatedSpriteScale.X;


      //check for camera zoom
      dX = ReadKeyboardAxis(currentKeyboardState, Keys.X, Keys.Z) *
          elapsed * ZoomRate;

      //limit the zoom
      camera.Zoom += dX;
      if (camera.Zoom < .5f) camera.Zoom = .5f;
      if (camera.Zoom > 2f) camera.Zoom = 2f;

      //check for camera reset
      if (currentKeyboardState.IsKeyDown(Keys.R) &&
          lastKeyboardState.IsKeyDown(Keys.R))
      {
        ResetToInitialPositions();
      }


      //Verifying if will enter in the game
      if (gameBoxSprite.Visible)
      {
        Vector2 pos = -camera.Position + gameBoxSprite.Origin + animatedSpritePosition;
        if (pos.X > 167 && pos.X < 240 - 60 - 3
          && pos.Y > 26 && pos.Y < 100 - 60 - 3) //gameBox margins
        {
          //ResetToInitialPositions();
          gameBoxSprite.Visible = false;
          switch (gameBoxSprite.Building)
          {
            case GameBuilding.Home:
              StartMiniGame(MiniGameType.Microgames);
              break;
            case GameBuilding.Restaurant:
              StartMiniGame(MiniGameType.Restaurant);
              break;
            case GameBuilding.River:
              StartMiniGame(MiniGameType.River);
              break;
            case GameBuilding.Pub:
              StartMiniGame(MiniGameType.Club);
              break;
            case GameBuilding.Forest:
              break;
            case GameBuilding.GamerHouse:
              break;
            case GameBuilding.HorrorHouse:
              break;
            default:
              break;
          }
        }
      }

    }

    public void HandleCursorInput(float elapsed)
    {
        if (Input.WiimoteConnected)
        {
            Crosshair cursor1 = Input.GetCursor(Input.Cursors.Cursor1);
            Vector2 currentPosition = cursor1.Position;

            if (currentPosition.Y < 0 && currentPosition.X < 0) return;

            //check for camera movement
            float dX = ReadWiimoteAxis(currentPosition) *
                elapsed * MovementRate;
            float dY = ReadWiimoteAxis(currentPosition) *
                elapsed * MovementRate;

            //check for animted sprite movement

            animatedSpritePosition.X = (currentPosition.X / camera.Zoom) + camera.Position.X;
            animatedSpritePosition.Y = (currentPosition.Y / camera.Zoom) + camera.Position.Y;


            if (animatedSpritePosition.X < 0) animatedSpritePosition.X = 0;
            if (animatedSpritePosition.Y < 0) animatedSpritePosition.Y = 0;

            if (animatedSpritePosition.X > (MAP_WIDTH - CURSOR_WIDTH)) animatedSpritePosition.X = (MAP_WIDTH - CURSOR_WIDTH);
            if (animatedSpritePosition.Y > (MAP_HEIGHT - CURSOR_HEIGHT)) animatedSpritePosition.Y = (MAP_HEIGHT - CURSOR_HEIGHT);

            dX = ReadWiimoteAxis(currentPosition) *
                elapsed * MovementRate;
            dY = ReadWiimoteAxis(currentPosition) *
                elapsed * MovementRate;

            if (currentPosition.X < 50 && dX <= 0)
            {
                if (dX == 0) dX = -5;
                camera.MoveRight(ref dX);
            }

            if (currentPosition.X > 750 && dX >= 0)
            {
                if (dX == 0) dX = 5;
                camera.MoveRight(ref dX);
            }

            if (currentPosition.Y < 50 && dY >= 0)
            {
                if (dY == 0) dY = 5;
                camera.MoveUp(ref dY);
            }

            if (currentPosition.Y > 550 && dY <= 0)
            {
                if (dY == 0) dY = -5;
                camera.MoveUp(ref dY);
            }


            //since the sprite position has changed, the Origin must be updated
            //on the animated sprite object

            animatedSprite.Origin = (camera.Position - animatedSpritePosition)
                    / animatedSpriteScale.X;

            if (cursor1.Size <= 2)
            {
                //zoom out
                camera.Zoom -= .01f;
            }
            else if (cursor1.Size >= 5)
            {
                //zoom in
                camera.Zoom += .01f;
            }
            if (camera.Zoom < .5f) camera.Zoom = .5f;
            if (camera.Zoom > 2f) camera.Zoom = 2f;
            //if (currentPosition.ScrollWheelValue != 0)
            //{
            //    float cam = camera.Zoom + (((float)currentPosition.ScrollWheelValue) / 10000.0f);

            //    if (cam < .5f) cam = .5f;
            //    if (cam > 2f) cam = 2f;
            //    camera.Zoom = cam;
            //}

            lastWiimoteX = (int)currentPosition.X;
            lastWiimoteY = (int)currentPosition.Y;
        }
        else
        {

            MouseState mouseState = Mouse.GetState();

            if (mouseState.Y < 0 && mouseState.X < 0) return;

            //check for camera movement
            float dX = ReadMouseAxis(mouseState, mouseState.X, mouseState.Y) *
                elapsed * MovementRate;
            float dY = ReadMouseAxis(mouseState, mouseState.X, mouseState.Y) *
                elapsed * MovementRate;

            //check for animted sprite movement

            animatedSpritePosition.X = (mouseState.X / camera.Zoom) + camera.Position.X;
            animatedSpritePosition.Y = (mouseState.Y / camera.Zoom) + camera.Position.Y;


            if (animatedSpritePosition.X < 0) animatedSpritePosition.X = 0;
            if (animatedSpritePosition.Y < 0) animatedSpritePosition.Y = 0;

            if (animatedSpritePosition.X > (MAP_WIDTH - CURSOR_WIDTH)) animatedSpritePosition.X = (MAP_WIDTH - CURSOR_WIDTH);
            if (animatedSpritePosition.Y > (MAP_HEIGHT - CURSOR_HEIGHT)) animatedSpritePosition.Y = (MAP_HEIGHT - CURSOR_HEIGHT);

            dX = ReadMouseAxis(mouseState, mouseState.X, mouseState.Y) *
                elapsed * MovementRate;
            dY = ReadMouseAxis(mouseState, mouseState.X, mouseState.Y) *
                elapsed * MovementRate;

            if (mouseState.X < 50 && dX <= 0)
            {
                if (dX == 0) dX = -5;
                camera.MoveRight(ref dX);
            }

            if (mouseState.X > 750 && dX >= 0)
            {
                if (dX == 0) dX = 5;
                camera.MoveRight(ref dX);
            }

            if (mouseState.Y < 50 && dY >= 0)
            {
                if (dY == 0) dY = 5;
                camera.MoveUp(ref dY);
            }

            if (mouseState.Y > 550 && dY <= 0)
            {
                if (dY == 0) dY = -5;
                camera.MoveUp(ref dY);
            }


            //since the sprite position has changed, the Origin must be updated
            //on the animated sprite object

            animatedSprite.Origin = (camera.Position - animatedSpritePosition)
                    / animatedSpriteScale.X;

            if (mouseState.ScrollWheelValue != 0)
            {
                float cam = camera.Zoom + (((float)mouseState.ScrollWheelValue) / 10000.0f);

                if (cam < .5f) cam = .5f;
                if (cam > 2f) cam = 2f;
                camera.Zoom = cam;
            }

            lastMouseX = mouseState.X;
            lastMouseY = mouseState.Y;
        }

    }

    /// <summary>
    /// This function is called when the camera's values have changed
    /// and is used to update the properties of the tiles and animated sprite
    /// </summary>
    public void CameraChanged()
    {
      //set rotation
      groundLayer.CameraRotation = camera.Rotation;


      //set zoom
      groundLayer.CameraZoom = camera.Zoom;
      animatedSprite.ScaleValue = animatedSpriteScale * camera.Zoom;
      cloudLayer.CameraZoom = camera.Zoom + 1.0f;

      //For an extra special effect, the camera zoom is figured into the cloud
      //alpha. The clouds will appear to fade out as camera zooms in.
      cloudLayer.Color = new Color(new Vector4(
              1.0f, 1.0f, 1.0f, 2 / (2f * camera.Zoom + 1.0f)));

      //set position
      groundLayer.CameraPosition = camera.Position;

      //to acheive a paralax effect, scale down cloud movement
      cloudLayer.CameraPosition = camera.Position / 3.0f;

      //The animcated sprite's origin is set so that rotation
      //will occur around the camera center (accounting for scale)
      animatedSprite.Origin = (camera.Position - animatedSpritePosition)
          / animatedSpriteScale.X;


      gameBoxSprite.Origin = animatedSprite.Origin;
      gameBoxSprite.ScaleValue = animatedSprite.ScaleValue;
      gameBoxSprite.Visible = false;

      //changes have been accounted for, reset the changed value so that this
      //function is not called unnecessarily
      camera.ResetChanged();
    }
    #endregion

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    public override void Draw(GameTime gameTime)
    {

      //since we're drawing in order from back to front,
      //depth buffer is disabled
      //graphics.GraphicsDevice.RenderState.DepthBufferEnable = false;
      //graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

      //draw the background layers
      groundLayer.Color = Color.LightGray;

      groundLayer.Draw(spriteBatch);

      //draw the clouds
      cloudLayer.Draw(spriteBatch);


      gameBoxSprite.Draw(spriteBatch, Color.White, SpriteBlendMode.AlphaBlend);


      animatedSprite.Draw(spriteBatch, Color.AntiqueWhite,
          SpriteBlendMode.AlphaBlend);

      //base.Draw(gameTime);
    }




    #endregion

    #region Handle Input

    /// <summary>
    /// Handles input for quitting the game.
    /// </summary>
    private void HandleInput()
    {
      lastKeyboardState = currentKeyboardState;
      lastGamePadState = currentGamePadState;

      currentKeyboardState = Keyboard.GetState();
      currentGamePadState = GamePad.GetState(PlayerIndex.One);

      //// Check for exit.
      //if (currentKeyboardState.IsKeyDown(Keys.Escape) ||
      //    currentGamePadState.Buttons.Back == ButtonState.Pressed)
      //{
      //  Exit();
      //}
    }

    /// <summary>
    /// Uses a pair of keys to simulate a positive or negative axis input.
    /// </summary>
    private static float ReadKeyboardAxis(KeyboardState keyState, Keys downKey,
                                          Keys upKey)
    {
      float value = 0;

      if (keyState.IsKeyDown(downKey))
        value -= 1.0f;

      if (keyState.IsKeyDown(upKey))
        value += 1.0f;

      return value;
    }

    /// <summary>
    /// Uses a pair of keys to simulate a positive or negative axis input.
    /// </summary>
    private static float ReadMouseAxis(MouseState mouseState, int mouseX,
                                          int mouseY)
    {
        float value = 0;

        //TODO: Change to mouse axis


        if (mouseX > lastMouseX)
            value += 1.0f;

        if (mouseY > lastMouseY)
            value += 1.0f;

        if (mouseX < lastMouseX)
            value -= 1.0f;

        if (mouseY < lastMouseY)
            value -= 1.0f;

        return value;
    }

    /// <summary>
    /// Uses a pair of keys to simulate a positive or negative axis input.
    /// </summary>
    private static float ReadWiimoteAxis(Vector2 position)
    {
      float value = 0;

      //TODO: Change to mouse axis


      if (position.X > lastWiimoteX)
        value += 1.0f;

      if (position.Y > lastWiimoteY)
        value += 1.0f;

      if (position.X < lastWiimoteX)
        value -= 1.0f;

      if (position.Y < lastWiimoteY)
        value -= 1.0f;

      return value;
    }
    #endregion

    #region Map



    private Rectangle GetBuildingRectangle(GameBuilding building)
    {
      switch (building)
      {
        case GameBuilding.Home:
          return new Rectangle(10, 30, 240, 229);
          break;
        case GameBuilding.Restaurant:
          return new Rectangle(847, 0, 284, 347);
          break;
        case GameBuilding.River:
          return new Rectangle(1807, 27, 233, 217);
          break;
        case GameBuilding.Pub:
          return new Rectangle(254, 437, 148, 222);
          break;
        case GameBuilding.Forest:
          return new Rectangle(42, 1189, 199, 198);
          break;
        case GameBuilding.GamerHouse:
          return new Rectangle(620, 460, 186, 198);
          break;
        case GameBuilding.HorrorHouse:
          return new Rectangle(1571, 1111, 228, 218);
          break;
        default:
          return new Rectangle();
          break;
      }
    }


    #endregion

    #region Utils
    private static void PauseGame()
    {
      GlobalContainer.gameStateManager.SetCurrentState(GameState.Paused);
    }

    public void StartMiniGame(MiniGameType gameType)
    {
      GlobalContainer.gameStateManager.SetActiveGame(gameType);
    }
    #endregion
  }

  public enum GameBuilding
  {
    Home,
    Restaurant,
    River,
    Pub,
    Forest,
    GamerHouse,
    HorrorHouse
  }
}
